Skip to content

Add JRuby to CI test job#255

Merged
crmne merged 7 commits intocrmne:mainfrom
headius:jruby_ci
Jul 16, 2025
Merged

Add JRuby to CI test job#255
crmne merged 7 commits intocrmne:mainfrom
headius:jruby_ci

Conversation

@headius
Copy link
Copy Markdown
Contributor

@headius headius commented Jun 19, 2025

What this does

This PR adds JRuby to CI. The initial set of changes include:

  • Fix hard dependency on sqlite3 gem to instead use the combination of jdbc-sqlite3 and activerecord-jdbcsqlite3-adapter supported by JRuby on Rails.
  • Only run rails-7.1 job on CI since JRuby's sqlite3 AR adapter does not currently support 7.2+.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Performance improvement

Scope check

  • I read the Contributing Guide
  • This aligns with RubyLLM's focus on LLM communication
  • This isn't application-specific logic that belongs in user code
  • This benefits most users, not just my specific use case

Quality check

  • I ran overcommit --install and all hooks pass
  • I tested my changes thoroughly
  • I updated documentation if needed
  • I didn't modify auto-generated files manually (models.json, aliases.json)

API changes

  • Breaking change
  • New public methods/classes
  • Changed method signatures
  • No API changes

Related issues

None.

@headius
Copy link
Copy Markdown
Contributor Author

headius commented Jun 19, 2025

Hello there! We had a user @rolandoam report trouble running ruby_llm on JRuby due to some Zeitwerk incompatibilities. Those issues are now resolved on JRuby master (10.0.x) and I wanted to start getting JRuby into your CI to prevent any future breakage.

The changes here get the test suite running and it mostly passes. There's two kinds of failures that remain:

  • All of the "handles context length exceeded errors" tests fail because they try to load a very large YAML file. JRuby's implementation of Psych (Ruby YAML stdlib) uses the SnakeYAML-Engine library, which has a default limit in input size to prevent DOS attacks. As a result we raise a different error for the excessive content:
  6) RubyLLM::Chat real error scenarios openrouter/anthropic/claude-3.5-haiku handles context length exceeded errors
     Failure/Error:
       expect { chat.ask('Hi') }.to raise_error(RubyLLM::Error) do |e|
         # Basic error format checks
         expect(e.message).not_to look_like_json
         expect(e.message).to match(/^[A-Za-z]/)
       end
     
       expected RubyLLM::Error, got #<Java::OrgSnakeyamlEngineV2Exceptions::YamlEngineException: The incoming YAML document exceeds the limit: 3145728 code points.> with backtrace:
         # org.snakeyaml.engine.v2.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:304)
         # org.snakeyaml.engine.v2.scanner.ScannerImpl.checkToken(ScannerImpl.java:193)
         # org.snakeyaml.engine.v2.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:712)
         # org.snakeyaml.engine.v2.parser.ParserImpl.lambda$produce$1(ParserImpl.java:232)
         # java.base/java.util.Optional.ifPresent(Optional.java:178)
         # org.snakeyaml.engine.v2.parser.ParserImpl.produce(ParserImpl.java:232)
         # org.snakeyaml.engine.v2.parser.ParserImpl.hasNext(ParserImpl.java:226)
         # org.jruby.ext.psych.PsychParser.parse(PsychParser.java:248)

We currently allow these exceptions to be raised directly from the YAML engine, which could be causing this to fail in a different way than you expect. This behavior accounts for six out of the eight failures.

  • The two remaining failures appear to be similar, both handling extended character sets in Tool#name. For some reason we're getting a nil result during the processing of the tool's name.
  7) RubyLLM::Tool#name normalizes class name Unicode characters to ASCII
     Failure/Error:
       normalized.encode('ASCII', replace: '')
                 .gsub(/[^a-zA-Z0-9_-]/, '-')
                 .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
                 .gsub(/([a-z\d])([A-Z])/, '\1_\2')
                 .downcase
                 .delete_suffix('_tool')
     
     NoMethodError:
       undefined method '[]' for nil
     # ./lib/ruby_llm/tool.rb:59:in 'name'
     # ./spec/ruby_llm/tool_spec.rb:16:in 'block in <main>'
     # ./spec/spec_helper.rb:105:in 'block in <main>'
     # ./spec/spec_helper.rb:104:in 'block in <main>'

The '[]' method reported here is actually due to normalized.encode('ASCII', replace: '') incorrectly trying to call [] on the string '' used for the ':replace` option rather than using it as-is. I think we're doing something wrong here.

headius added 2 commits June 20, 2025 11:48
JRuby's YAML backend, SnakeYAML, has a default codepoint limit to
prevent large content from leading to a DOS. The limit needs to be
increased here to allow it to propagate through the rest of the
test, or it will raise too early and fail.

See ruby/psych#647
@headius
Copy link
Copy Markdown
Contributor Author

headius commented Jun 20, 2025

I have fixed the encoding issue in jruby/jruby#8873 and bumped up the Psych codepoint limit in this PR and now ruby_llm is green on JRuby!

I'd love to see it green in your CI too... could someone approve the workflow?

The encoding fix will be in JRuby 10.0.1.0 so for now I've bumped the CI job to use jruby-head.

@crmne crmne added the enhancement New feature or request label Jul 16, 2025
@crmne
Copy link
Copy Markdown
Owner

crmne commented Jul 16, 2025

Would be awesome to make RubyLLM run on JRuby as well!

However, the overcommit hooks are there for a reason. Can you fix the rubocop errors by running rubocop -A?

@headius
Copy link
Copy Markdown
Contributor Author

headius commented Jul 16, 2025

Thank you for approving the run!

I will fix the issues, but I strongly disagree with the strict alphabetical ordering of dependencies. In this case, jdbc-sqlite3 is the alternative library for sqlite3 and it makes much more sense to have related platform-specific dependencies near each other. The move of activerecord-jdbcslite3-adapter is less of a concern.

In general I believe that related dependencies should be grouped together in a Gemfile rather than alphabetically ordered, which results in related deps being placed far from one another. When you need to inspect dependencies, logical groupings make it much easier to manage.

But it's your project and I'll comply!

@crmne
Copy link
Copy Markdown
Owner

crmne commented Jul 16, 2025

I agree with you. If with a rubocop disable comment you're able to skip the alphabetical ordering only for the JRuby dependencies I'd prefer that.

@headius
Copy link
Copy Markdown
Contributor Author

headius commented Jul 16, 2025

@crmne Oops, I already pushed the change. I can reverse it with a comment if you would prefer.

@crmne
Copy link
Copy Markdown
Owner

crmne commented Jul 16, 2025

@headius if there's a comment that would keep the alphabetical order enabled for all deps except JRuby that's what I would prefer. Otherwise the current commit works for me.

@headius
Copy link
Copy Markdown
Contributor Author

headius commented Jul 16, 2025

@crmne There doesn't seem to be a way to exclude just the JRuby dependencies, unfortunately.

@crmne
Copy link
Copy Markdown
Owner

crmne commented Jul 16, 2025

Ok. I'll keep the JRuby dependencies in mind when looking at that list. Thank you!

@crmne
Copy link
Copy Markdown
Owner

crmne commented Jul 16, 2025

Looks like there's one last thing to fix (with a comment)

This avoids RuboCop requiring total ordering of dependencies and
gets around the "too many lines" cop for the development block.
@headius
Copy link
Copy Markdown
Contributor Author

headius commented Jul 16, 2025

I figured out that commenting the dependencies and sorting them within that smaller group solves both cops. rubocop -A is green now.

@codecov
Copy link
Copy Markdown

codecov bot commented Jul 16, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.91%. Comparing base (1212984) to head (6a08ac0).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #255      +/-   ##
==========================================
- Coverage   89.72%   88.91%   -0.81%     
==========================================
  Files          75       75              
  Lines        2812     2860      +48     
  Branches      556      556              
==========================================
+ Hits         2523     2543      +20     
- Misses        289      317      +28     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@crmne crmne merged commit 4ff492d into crmne:main Jul 16, 2025
15 checks passed
@headius headius deleted the jruby_ci branch July 16, 2025 16:24
parruda pushed a commit to parruda/ruby_llm that referenced this pull request Nov 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants